// Copyright (C) ZHENG Zhong <heavyzheng nospam-at gmail D0T com>
//
// $Id: basic_node_iterator.hpp 210 2008-08-28 10:10:41Z heavyzheng $
//

#ifndef ZZHENG_XML_DOM_BASIC_NODE_ITERATOR_HPP_20080721__
#define ZZHENG_XML_DOM_BASIC_NODE_ITERATOR_HPP_20080721__

#include <zzheng/xml/config.hpp>
#include <zzheng/xml/dom/basic_node_ptr.hpp>

namespace zzheng {
namespace xml {
namespace dom {

    ////////////////////////////////////////////////////////////////////////////////////////////////
    // basic_node_iterator
    //

    //! This class template represents an iterator to an XML node object. Increasing the iterator
    //! will move to the next sibling node of the current node; decreasing the iterator will move
    //! to the previous sibling node of the current node. It is required the template parameter T
    //! provide the following member functions:
    //!
    //! \code
    //! // Required by basic_node_iterator<T>:
    //! basic_node_ptr<T> T::next_sibling();
    //! basic_node_ptr<T> T::prev_sibling();
    //!
    //! // Required by basic_node_iterator<const T>:
    //! basic_node_ptr<const T> T::next_sibling() const;
    //! basic_node_ptr<const T> T::prev_sibling() const;
    //! \endcode
    //!
    //! This class template is used in combination with child_node and attribute.
    //! \todo TODO: decreasing an end iterator may result in undefined behavior, fix this.
    template<class T>
    class basic_node_iterator {

        template<class U> friend class basic_node_iterator;

        typedef basic_node_iterator<T> this_type;

    public:

        typedef T           value_type;
        typedef value_type& reference;
        typedef value_type* pointer;

    public:

        explicit basic_node_iterator(): current_() {
            // Do nothing.
        }

        explicit basic_node_iterator(value_type* current): current_(current) {
            // Do nothing.
        }

        //! Constructs a basic_node_iterator from another basic_node_iterator. This non-explicit
        //! constructor requires that type U* is implicitly convertible to type T* (e.g. U is a
        //! subclass of T).
        template<class U>
        basic_node_iterator(const basic_node_iterator<U>& rhs): current_(rhs.current_) {
                // Do nothing.
            }

        // Use auto-generated copy constructor.
        // Use auto-generated copy assignment.
        // Use auto-generated destructor.

        bool operator==(const this_type& rhs) const {
            return (current_ == rhs.current_);
        }

        bool operator!=(const this_type& rhs) const {
            return (current_ != rhs.current_);
        }

        reference operator*() const {
            return (*current_);
        }

        pointer operator->() const {
            return (current_.operator->());
        }

        //! Prefix-increment operator. If the iterator exceeds the end node, it will be set to
        //! empty (which equals to a default-constructed iterator object).
        this_type& operator++() {
            increment();
            return *this;
        }

        this_type operator++(int) {
            this_type tmp = *this;
            increment();
            return tmp;
        }

        this_type& operator--() {
            decrement();
            return *this;
        }

        this_type operator--(int) {
            this_type tmp = *this;
            decrement();
            return tmp;
        }

        basic_node_ptr<T> ptr() const {
            return current_;
        }

    private:

        void increment() {
            current_ = current_->next_sibling();
        }

        void decrement() {
            current_ = current_->prev_sibling();
        }

    private:

        basic_node_ptr<T> current_;

    }; // class basic_node_iterator<T>

} // namespace zzheng::xml::dom
} // namespace zzheng::xml
} // namespace zzheng

#endif // ZZHENG_XML_DOM_BASIC_NODE_ITERATOR_HPP_20080721__




